"""
数据获取服务
支持从多个免费数据源获取股票数据
"""

import akshare as ak
import pandas as pd
from typing import List, Dict, Optional
from datetime import datetime, timedelta
import logging

logger = logging.getLogger(__name__)


class DataService:
    """数据获取服务"""
    
    def __init__(self):
        self.akshare_available = True
        try:
            # 测试AKShare是否可用
            ak.stock_zh_a_spot_em()
        except Exception as e:
            logger.warning(f"AKShare不可用: {e}")
            self.akshare_available = False
    
    def get_stock_list(self) -> List[Dict]:
        """获取A股股票列表"""
        try:
            if self.akshare_available:
                df = ak.stock_zh_a_spot_em()
                stocks = []
                for _, row in df.head(100).iterrows():  # 限制前100只股票避免过多数据
                    stocks.append({
                        "code": row["代码"],
                        "name": row["名称"],
                        "price": float(row["最新价"]) if row["最新价"] != "-" else 0.0,
                        "change": float(row["涨跌额"]) if row["涨跌额"] != "-" else 0.0,
                        "change_percent": float(row["涨跌幅"]) if row["涨跌幅"] != "-" else 0.0,
                        "volume": int(row["成交量"]) if row["成交量"] != "-" else 0,
                        "amount": float(row["成交额"]) if row["成交额"] != "-" else 0.0,
                        "market": "SZ" if row["代码"].startswith(("000", "002", "300")) else "SH"
                    })
                return stocks
            else:
                # 返回模拟数据
                return self._get_mock_stock_data()
        except Exception as e:
            logger.error(f"获取股票列表失败: {e}")
            return self._get_mock_stock_data()
    
    def search_stocks(self, keyword: str) -> List[Dict]:
        """搜索股票"""
        try:
            stocks = self.get_stock_list()
            if not keyword:
                return stocks[:10]
            
            # 简单的关键字搜索
            filtered_stocks = []
            for stock in stocks:
                if (keyword.lower() in stock["code"].lower() or 
                    keyword in stock["name"]):
                    filtered_stocks.append(stock)
            
            return filtered_stocks[:10]
        except Exception as e:
            logger.error(f"搜索股票失败: {e}")
            return []
    
    def get_stock_daily_data(self, stock_code: str, start_date: Optional[str] = None, end_date: Optional[str] = None) -> List[Dict]:
        """获取股票日K数据"""
        try:
            if not start_date:
                start_date = (datetime.now() - timedelta(days=90)).strftime("%Y%m%d")
            if not end_date:
                end_date = datetime.now().strftime("%Y%m%d")
            
            if self.akshare_available:
                # 移除股票代码中的市场后缀
                code = stock_code.split('.')[0]
                df = ak.stock_zh_a_hist(symbol=code, period="daily", start_date=start_date, end_date=end_date)
                
                daily_data = []
                for _, row in df.iterrows():
                    daily_data.append({
                        "date": row["日期"].strftime("%Y-%m-%d"),
                        "open": float(row["开盘"]),
                        "high": float(row["最高"]),
                        "low": float(row["最低"]),
                        "close": float(row["收盘"]),
                        "volume": int(row["成交量"]),
                        "amount": float(row["成交额"])
                    })
                return daily_data
            else:
                # 返回模拟数据
                return self._get_mock_daily_data()
        except Exception as e:
            logger.error(f"获取股票日K数据失败 {stock_code}: {e}")
            return self._get_mock_daily_data()
    
    def get_realtime_price(self, stock_code: str) -> Optional[Dict]:
        """获取实时股价"""
        try:
            if self.akshare_available:
                code = stock_code.split('.')[0]
                df = ak.stock_zh_a_spot_em()
                stock_data = df[df["代码"] == code]
                
                if not stock_data.empty:
                    row = stock_data.iloc[0]
                    return {
                        "code": stock_code,
                        "name": row["名称"],
                        "price": float(row["最新价"]) if row["最新价"] != "-" else 0.0,
                        "change": float(row["涨跌额"]) if row["涨跌额"] != "-" else 0.0,
                        "change_percent": float(row["涨跌幅"]) if row["涨跌幅"] != "-" else 0.0,
                        "volume": int(row["成交量"]) if row["成交量"] != "-" else 0,
                        "amount": float(row["成交额"]) if row["成交额"] != "-" else 0.0,
                        "timestamp": datetime.now().isoformat()
                    }
            
            # 返回模拟数据
            return {
                "code": stock_code,
                "name": "测试股票",
                "price": 10.50,
                "change": 0.15,
                "change_percent": 1.45,
                "volume": 1000000,
                "amount": 10500000.0,
                "timestamp": datetime.now().isoformat()
            }
        except Exception as e:
            logger.error(f"获取实时股价失败 {stock_code}: {e}")
            return None
    
    def _get_mock_stock_data(self) -> List[Dict]:
        """获取模拟股票数据"""
        return [
            {
                "code": "000001.SZ",
                "name": "平安银行",
                "price": 10.50,
                "change": 0.05,
                "change_percent": 0.48,
                "volume": 1000000,
                "amount": 10500000.0,
                "market": "SZ"
            },
            {
                "code": "000002.SZ",
                "name": "万科A",
                "price": 8.20,
                "change": -0.10,
                "change_percent": -1.20,
                "volume": 2000000,
                "amount": 16400000.0,
                "market": "SZ"
            },
            {
                "code": "600000.SH",
                "name": "浦发银行",
                "price": 7.80,
                "change": 0.12,
                "change_percent": 1.56,
                "volume": 1500000,
                "amount": 11700000.0,
                "market": "SH"
            },
            {
                "code": "600036.SH",
                "name": "招商银行",
                "price": 35.60,
                "change": 0.80,
                "change_percent": 2.30,
                "volume": 800000,
                "amount": 28480000.0,
                "market": "SH"
            },
            {
                "code": "000858.SZ",
                "name": "五粮液",
                "price": 128.50,
                "change": -2.30,
                "change_percent": -1.76,
                "volume": 500000,
                "amount": 64250000.0,
                "market": "SZ"
            }
        ]
    
    def _get_mock_daily_data(self) -> List[Dict]:
        """获取模拟日K数据"""
        import random
        daily_data = []
        base_price = 10.0
        
        for i in range(30):  # 30天的数据
            date = (datetime.now() - timedelta(days=30-i)).strftime("%Y-%m-%d")
            change = random.uniform(-0.5, 0.5)
            base_price += change
            
            open_price = base_price + random.uniform(-0.2, 0.2)
            close_price = base_price + random.uniform(-0.2, 0.2)
            high_price = max(open_price, close_price) + random.uniform(0, 0.5)
            low_price = min(open_price, close_price) - random.uniform(0, 0.3)
            
            daily_data.append({
                "date": date,
                "open": round(open_price, 2),
                "high": round(high_price, 2),
                "low": round(low_price, 2),
                "close": round(close_price, 2),
                "volume": random.randint(500000, 2000000),
                "amount": round(close_price * random.randint(500000, 2000000), 2)
            })
        
        return daily_data